package com.learning.rpc.remoting.netty;

import com.learning.rpc.remoting.Codec;
import com.learning.rpc.remoting.Handler;
import com.learning.rpc.remoting.Server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;
import java.net.URI;

/**
 * ClassName: NettyServer
 * Description: Netty 服务端
 * Date: 2022/5/10 22:45 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class NettyServer implements Server {

    /**
     * 开启一个网络服务
     * 创建时间循环组
     */
    private EventLoopGroup boss = new NioEventLoopGroup();
    private EventLoopGroup worker = new NioEventLoopGroup();

    @Override
    public void start(URI uri, Codec codec, Handler handler) {
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, worker)
                    // 指定锁使用的NIO传输 channel
                    .channel(NioServerSocketChannel.class)
                    // 指定要监听的地址
                    .localAddress(new InetSocketAddress(uri.getHost(), uri.getPort()))
                    // 添加Handler，有连接之后处理的处理逻辑
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 协议编解码。不同的请求需要使用自己的编解码器（线程安全）
                            socketChannel.pipeline().addLast(new NettyCodec(codec.createInstance()));
                            // 具体的逻辑执行
                            socketChannel.pipeline().addLast(new NettyHandler(handler));
                        }
                    });
            final ChannelFuture future = bootstrap.bind().sync();
            System.out.println("完成端口绑定和服务器启动");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}